package metadatabrowser;

import at.fhj.Application;

import at.fhj.itm.generator.SqlCodeGenerator;
import at.fhj.itm.generator.postgres.PostgresSqlCodeGenerator;
import at.fhj.itm.metadata.Constraint;
import at.fhj.itm.metadata.ForeignKeyConstraint;
import at.fhj.itm.metadata.Index;
import at.fhj.itm.metadata.MetaDataException;
import at.fhj.itm.metadata.MetadataProvider;
import at.fhj.itm.metadata.Procedure;
import at.fhj.itm.metadata.Schema;
import at.fhj.itm.metadata.Sequence;
import at.fhj.itm.metadata.impl.postgres.PostgresMetadataProvider;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import net.miginfocom.swt.MigLayout;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.StatusLineManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;

import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
/**
 *
 * @author Seuchter
 */
public class MainWindow extends ApplicationWindow
{

    private Button btnConnect;
    private List<? extends Schema> metadata;
    private Tree treeSchema;
    private Table tblProperties;
    private MetadataProvider provider;
    private PropertiesColumnBuilder colBuilder = new PropertiesColumnBuilder();
    private TableViewer propertiesTableViewer;
    private SqlCodeGenerator codeGenerator;
    private Text txtSqlCode;
    public MainWindow()
    {
        super(null);
        codeGenerator = new PostgresSqlCodeGenerator();
        addStatusLine();
        setBlockOnOpen(true);
        open();

        Display.getCurrent().dispose();

    }

    @Override
    protected MenuManager createMenuManager() {
    	MenuManager menuMgr = new MenuManager();
    	return menuMgr;
    }
    
    @Override
    protected StatusLineManager createStatusLineManager()
    {
        StatusLineManager slm = new StatusLineManager();
        return slm;
    }

    @Override
    protected Control createContents(Composite parent)
    {

        this.getShell().setText("Meta Data Browser");
        MigLayout layout = new MigLayout("fill", "[grow,fill][][]");

        Composite root = new Composite(parent, 0);
        root.setLayout(layout);
        Control conAerea = createConnectionArea(root);
        conAerea.setLayoutData("wrap");
        getStatusLineManager().setMessage("Not connected.");



        SashForm outerSashForm = new SashForm(root, SWT.VERTICAL);

        SashForm innerSashForm = new SashForm(outerSashForm, SWT.HORIZONTAL);

        txtSqlCode = new Text(outerSashForm, SWT.MULTI | SWT.WRAP | SWT.BORDER |
                SWT.V_SCROLL | SWT.H_SCROLL );


        outerSashForm.setLayoutData("dock center");

        treeSchema = new Tree(innerSashForm, SWT.BORDER);


        tblProperties = new Table(innerSashForm, SWT.BORDER);

        propertiesTableViewer = new TableViewer(tblProperties);


        colBuilder.buildColumns(propertiesTableViewer);
        propertiesTableViewer.setLabelProvider(new TableTableLabelProvider());
        updateButtonStatus();

        return root;

    }

    private void initTableViewer()
    {
        for (TableColumn c : tblProperties.getColumns())
        {
            c.dispose();

        }
        propertiesTableViewer = new TableViewer(tblProperties);


        colBuilder.buildColumns(propertiesTableViewer);
        propertiesTableViewer.setLabelProvider(new TableTableLabelProvider());

    }

    private void OnSelectionChanged(SelectionChangedEvent ev)
    {
        if (ev.getSelection().isEmpty())
        {
            return;
        }
        if (ev.getSelection() instanceof IStructuredSelection)
        {

            IStructuredSelection sel = (IStructuredSelection) ev.getSelection();
            Object o = sel.toList().get(0);
            if (o instanceof Schema)
            {
                initTableViewer();
                String code = codeGenerator.generateSchema((Schema) o);
                txtSqlCode.setText(code);
            }
            if (o instanceof at.fhj.itm.metadata.Table)
            {
                initTableViewer();
                propertiesTableViewer.setContentProvider(new TableContentProvider());
                propertiesTableViewer.setInput(o);
                String code = codeGenerator.generateTable((at.fhj.itm.metadata.Table) o);
                txtSqlCode.setText(code);

            }
            else if (o instanceof at.fhj.itm.metadata.Column)
            {
                initTableViewer();
                propertiesTableViewer.setContentProvider(new ColumnContentProvider());
                propertiesTableViewer.setInput(o);
                String code = codeGenerator.generateColumn((at.fhj.itm.metadata.Column) o);
                txtSqlCode.setText(code);
            }
            else if (o instanceof ForeignKeyConstraint)
            {
                initTableViewer();
                propertiesTableViewer.setContentProvider(new ForeignKeyConstraintContentProvider());
                propertiesTableViewer.setInput(o);
                String code = codeGenerator.generateConstraint((at.fhj.itm.metadata.Constraint) o);
                txtSqlCode.setText(code);
            }
            else if(o instanceof Constraint)
            {
                initTableViewer();
                propertiesTableViewer.setContentProvider(new SimpleConstraintContentProvider());
                propertiesTableViewer.setInput(o);
                String code = codeGenerator.generateConstraint((at.fhj.itm.metadata.Constraint) o);
                txtSqlCode.setText(code);
            }
             else if(o instanceof Procedure){
                initTableViewer();;
                propertiesTableViewer.setContentProvider(new ProcedureContentProvider());
                String code = codeGenerator.generateProcedure((Procedure) o);
                propertiesTableViewer.setInput(o);
                txtSqlCode.setText(code);
             }
            else if(o instanceof Sequence)
            {
                initTableViewer();
                propertiesTableViewer.setContentProvider(new SequenceContentProvider());
                propertiesTableViewer.setInput(o);
                String code = codeGenerator.generateSequence((Sequence) o);
                txtSqlCode.setText(code);

            }
            else if(o instanceof Index)
            {
                initTableViewer();
                propertiesTableViewer.setContentProvider(new IndexContentProvider());
                propertiesTableViewer.setInput(o);
                String code = codeGenerator.generateIndex((Index) o);
                txtSqlCode.setText(code);
            }


        }

    }

    private void updateButtonStatus()
    {
        btnConnect.setEnabled(!Application.hasConnection());
    }

    private void connect(final String connectionStr)
    {

        try
        {
            Application.getConnection(connectionStr);
            getStatusLineManager().setMessage("Database connected");

            provider = new PostgresMetadataProvider(Application.getConnection());
            metadata = provider.getSchema();
            ITreeContentProvider contentProvider = new SchemaTreeContentProvider(metadata);
            ILabelProvider labelProvider = new SchemaTreeLabelProvider();
            TreeViewer viewer = new TreeViewer(treeSchema);
            viewer.setContentProvider(contentProvider);
            viewer.setLabelProvider(labelProvider);
            viewer.setInput("root");

            viewer.addSelectionChangedListener(new ISelectionChangedListener()
            {

                @Override
                public void selectionChanged(SelectionChangedEvent sce)
                {
                    MainWindow.this.OnSelectionChanged(sce);
                }
            });



        } catch (MetaDataException ex)
        {
            StringWriter sw = new StringWriter();
            ex.printStackTrace(new PrintWriter(sw));

            IStatus status = new Status(IStatus.ERROR, "MetadataBrowser", sw.toString());
            ErrorDialog.openError(getShell(), "Error opening database", "Error while connecting to database", status);
            getStatusLineManager().setErrorMessage("Error connecting to database.");
        }

        updateButtonStatus();
    }

    private Control createConnectionArea(Composite parent)
    {
        Composite connectArea = new Composite(parent, 0);
        MigLayout layout = new MigLayout("",
                "[pref!][grow,fill][]");
        final Label lblConStr = new Label(connectArea, 0);
        lblConStr.setText("JDBC: ");
        final Text txtConStr = new Text(connectArea, SWT.BORDER);
        txtConStr.setText("jdbc:postgresql://localhost/dellstore2");
        btnConnect = new Button(connectArea, SWT.PUSH);
        btnConnect.setText("Connect");
        btnConnect.addSelectionListener(new SelectionListener()
        {

            @Override
            public void widgetSelected(SelectionEvent e)
            {
                MainWindow.this.connect(txtConStr.getText());
            }

            @Override
            public void widgetDefaultSelected(SelectionEvent e)
            {
            }
        });

        connectArea.setLayout(layout);

        return connectArea;

    }
}
